<template>
    <div class="containers">
        <el-card>
            <div slot="header">
                <div style="text-align: right">
                    <span class="title">{{editTitle}}</span>
                    <el-button-group>
                        <input v-show="false" ref="file" type="file" @change="handleImportFile"></input>
                        <el-button size="medium" icon="el-icon-folder-opened" @click="handleOpen">打开</el-button>
                        <el-button size="medium" icon="el-icon-plus" @click="createNewViewer(initialDiagram)">新建
                        </el-button>
                        <el-button size="medium" icon="el-icon-download" @click="saveDiagram(true)">导出XML</el-button>
                        <el-button size="medium" icon="el-icon-picture-outline" @click="downloadSVG">导出图片</el-button>
                        <el-button size="medium" icon="el-icon-refresh-left" @click="handleUndo">撤销</el-button>
                        <el-button size="medium" icon="el-icon-refresh-right" @click="handleRedo">恢复</el-button>
                        <el-button size="medium" icon="el-icon-aim" @click="handleZoom(null)">重置</el-button>
                        <el-button size="medium" icon="el-icon-zoom-in" @click="handleZoom(0.1)">放大</el-button>
                        <el-button size="medium" icon="el-icon-zoom-out" @click="handleZoom(-0.1)">缩小</el-button>
                        <el-button size="medium" ref="saveDiagram" icon="el-icon-coin" @click="saveDiagram(false)">保存
                        </el-button>
                        <el-button size="medium" icon="el-icon-back" @click="handleReBack">返回</el-button>
                    </el-button-group>
                </div>
            </div>
            <el-row>
                <el-col :span="18">
                    <div class="dj-canvas" ref="dj-canvas" id="dj-canvas"></div>
                </el-col>
                <el-col :span="6">
                    <property-panel ref="propertyPanel" v-if="bpmnModeler" :modeler="bpmnModeler" :rowData="rowData"
                                    @handleCallConfigBack="handleCallConfigBack"></property-panel>
                </el-col>
            </el-row>
        </el-card>
    </div>
</template>

<script>
    import {getFormProperty} from '../../../utils/utils'
    import PropertyPanel from "./PropertyPanel";
    import BpmnModeler from 'bpmn-js/lib/Modeler'
    // BPMN读写，与流程引擎相关联
    import customTranslate from '../../../assets/customTranslate/customTranslate';
    import 'bpmn-js/dist/assets/diagram-js.css';
    import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css';
    import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css';
    import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css';
    /*右边工具栏样式*/
    import 'bpmn-js-properties-panel/dist/assets/bpmn-js-properties-panel.css';

    export default {
        name: "EditWorkflow",
        components: {PropertyPanel},
        component: {
            PropertyPanel
        },
        props: {
            editTitle: {
                type: String,
                default: "提示信息"
            },
            dialogVisible: {
                type: Boolean,
                required: true
            },
            rowData: {
                type: Object,
                required: false
            }
        },
        watch: {
            rowData: function (newVal, oldVal) {
            }
        },
        data() {
            return {
                // bpmn建模器
                bpmnModeler: null,
                xmlStr: null,
                svgStr: null,
                processName: '',
                zoomScale: 1, // 流程图比例
                initialDiagram:
                    '<?xml version="1.0" encoding="UTF-8"?>' +
                    '<bpmn:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' +
                    'xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" ' +
                    'xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" ' +
                    'xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" ' +
                    'targetNamespace="http://bpmn.io/schema/bpmn" id="Definitions_1">' +
                    '<bpmn:process id="Process_1" isExecutable="true">' +
                    '<bpmn:startEvent id="StartEvent_1"/>' +
                    '</bpmn:process>' +
                    '<bpmndi:BPMNDiagram id="BPMNDiagram_1">' +
                    '<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">' +
                    '<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">' +
                    '<dc:Bounds height="36.0" width="36.0" x="173.0" y="102.0"/>' +
                    '</bpmndi:BPMNShape>' +
                    '</bpmndi:BPMNPlane>' +
                    '</bpmndi:BPMNDiagram>' +
                    '</bpmn:definitions>'
            }
        },
        methods: {
            handleCallConfigBack(param) {
                console.log(param);
            },
            //返回
            handleReBack() {
                this.$emit("callBackFromSub", true);
            },
            //创建流程视图
            createBpmnModeler() {
                const translate = {
                    translate: ['value', customTranslate]
                };
                const camundaModdleDescriptor = require('camunda-bpmn-moddle/resources/camunda');
                // 获取到属性ref为"canvas"的dom节点
                const dj_canvas = this.$refs['dj-canvas'];
                // 新建modeler实例，并挂载到dom节点上
                this.bpmnModeler = new BpmnModeler({
                    container: dj_canvas,
                    additionalModules: [translate],
                    moddleExtensions: {
                        camunda: camundaModdleDescriptor
                    }
                });
                this.createNewViewer(this.initialDiagram);
            },
            //创建视图
            async createNewViewer(param, operate) {
                const _this = this;
                //bpmn-js 7.X 版本写法  https://github.com/bpmn-io/bpmn-js-callbacks-to-promises
                try {
                    const result = await _this.bpmnModeler.importXML(param);
                    const {warnings} = result;
                    operate ? _this.$successMsg(operate + "成功") : null;
                    console.log(warnings);
                } catch (err) {
                    operate ? _this.$errorMsg(operate + "失败") : null;
                    console.log(err.message, err.warnings);
                }
            },
            //下载svg
            async downloadSVG() {
                let _this = this;
                try {
                    const result = await _this.bpmnModeler.saveSVG();
                    const {svg} = result;
                    let a = document.createElement('a');
                    a.href = 'data:application/bpmn20-xml;charset=UTF-8,' + encodeURIComponent(svg);
                    a.download = "diagram.svg";
                    a.click();
                    _this.$successMsg("导出成功");
                } catch (err) {
                    _this.$errorMsg("导出失败");
                }
            },
            //保存视图
            async saveDiagram(isDownLoad) {
                let _this = this;
                const modelId = this.rowData ? this.rowData.id : null;
                const $propertyPanel = this.$refs['propertyPanel'];
                try {
                    const result = await _this.bpmnModeler.saveXML({format: true});
                    const {xml} = result;
                    //下载
                    _this.xmlStr = xml;
                    if (isDownLoad) {
                        let a = document.createElement('a');
                        a.href = 'data:application/bpmn20-xml;charset=UTF-8,' + encodeURIComponent(xml);
                        a.download = "diagram.bpmn";
                        a.click();
                    } else {
                        //保存
                        try {
                            const result = await _this.bpmnModeler.saveSVG();
                            const {svg} = result;
                            const process = $propertyPanel.process;
                            $propertyPanel.$refs["processForm"].validate((valid) => {
                                if (valid) {
                                    //xml 转为 json
                                    let xml2js = _this.$x2js.xml2js(_this.xmlStr.replace("Process_1", process.key));
                                    //camunda 转为 activiti
                                    getFormProperty(xml2js)
                                    //json 转为 xml
                                    let js2xml = _this.$x2js.js2xml(xml2js);
                                    let param = {
                                        name: process.processName,
                                        category: process.category,
                                        key: process.key,
                                        description: process.description,
                                        json_xml: js2xml,
                                        svg_xml: svg
                                    };
                                    if (modelId) {
                                        //编辑
                                        _this.$httpPut(_this.$axiosFlowHttp, "api/rest/model/upd/" + modelId, param).then((res) => {
                                            if (res.code === 200) {
                                                _this.$successMsg("保存成功");
                                            } else {
                                                _this.$errorMsg("保存失败");
                                            }
                                        });
                                    } else {
                                        //新增
                                        _this.$httpPost(_this.$axiosFlowHttp, "api/rest/model/save", param).then((res) => {
                                            if (res.code === 200) {
                                                _this.$successMsg("保存成功");
                                            } else {
                                                _this.$errorMsg("保存失败");
                                            }
                                        });
                                    }
                                } else {
                                    return false;
                                }
                            });
                        } catch (err) {
                            _this.$errorMsg("保存出错");
                        }
                    }
                } catch (err) {
                    _this.$errorMsg("保存出错");
                }
            },
            // 前进
            handleRedo() {
                this.bpmnModeler.get('commandStack').redo();
            },
            // 后退
            handleUndo() {
                this.bpmnModeler.get('commandStack').undo();
            },
            //缩放
            handleZoom(radio) {
                // 不输入radio则还原
                const newScale = !radio ? 1.0 : ((this.zoomScale + radio <= 0.2) ? 0.2 : (this.zoomScale + radio));
                this.bpmnModeler.get('canvas').zoom(newScale);
                this.zoomScale = newScale;
            },
            //打开文件
            handleOpen() {
                this.$refs['file'].click();
            },
            //导入文件
            handleImportFile(e) {
                const _this = this;
                const file = e.target.files[0];
                const reader = new FileReader();
                let data = '';
                reader.readAsText(file);
                reader.onload = function (event) {
                    data = event.target.result;
                    _this.createNewViewer(data, "打开文件");
                };
                this.$refs['file'].value = null;
            },
            getModelXmlByModelId(modelId) {
                this.$httpGet(this.$axiosFlowHttp, "api/rest/model/" + modelId + "/xml", {}).then((res) => {
                    if (res.code === 200) {
                        this.xmlStr = res.data;
                        this.createNewViewer(res.data.xmlStr, "查询流程模型");
                    } else {
                        this.$errorMsg("未查询到此流程模型信息");
                    }
                });
            }
        },
        mounted() {
            // 渲染图画
            this.createBpmnModeler(this.initialDiagram);
            if (this.rowData && this.rowData.id) {
                this.getModelXmlByModelId(this.rowData.id);
            }
        },
        destroyed() {
            //销毁实例
            this.bpmnModeler.destroy();
        }
    }
</script>

<style scoped lang="scss">
    .title {
        float: left;
        display: inline-block;
        padding-left: 10px;
        line-height: 32px;
    }

    /deep/ .djs-tooltip-container {
        position: absolute;
        width: 0px;
        height: 0px;
        transform: matrix(1, 0, 0, 1, 0, 0);
    }

    /deep/ .el-card__header {
        padding: 5px 5px;
        border-bottom: 1px solid #EBEEF5;
    }

    /deep/ .el-card__body {
        padding: 5px;
    }

    /deep/ .el-tabs--border-card {
        background: #FFF;
        border: 1px solid #DCDFE6;
        box-shadow: none;
    }

    .dj-canvas {
        height: calc(100vh - 180px);
    }

    /deep/ .bjs-powered-by {
        display: none;
    }
</style>
